home *** CD-ROM | disk | FTP | other *** search
- /*-----------------------------------------------------------------
-
- ZapTCP application patch sample
-
- Steve Falkeburg MacDTS 6/29/93
- written in Think C 6.0
-
- -----------------------------------------------------------------*/
-
- #ifndef __TYPES__
- #include <Types.h>
- #endif
-
- #ifndef __MEMORY__
- #include <Memory.h>
- #endif
-
- #ifndef __DEVICES__
- #include <Devices.h>
- #endif
-
- #ifndef __MEMORY__
- #include <Memory.h>
- #endif
-
- #ifndef __PACKAGES__
- #include <Packages.h>
- #endif
-
- #ifndef __NOTIFICATION__
- #include <Notification.h>
- #endif
-
- #ifndef __TRAPS__
- #include <Traps.h>
- #endif
-
- #ifndef THINK_C
- #include <SysEqu.h>
- #include <strings.h>
- #endif
-
- #include <MacTCPCommonTypes.h>
- #include <TCPPB.h>
-
- #include <stdio.h>
- #include <string.h>
-
-
- /*** DEFINES ***/
-
- #define kRAMBasedMask (1<<6)
- #define kDrvrOpenMask (1<<5)
- #define kDriverNameOffset 0x12
-
-
- /*** GLOBALS ***/
-
- static long etsAddr; // previous trap address of _ExitToShell
-
-
- /*** PROTOTYPES ***/
-
- pascal void ExitToShellPatch(void);
- OSErr ZapTCP(void);
- void AlertConnReleased(unsigned long remoteHost,unsigned short remotePort);
- void AlertStreamReleased(unsigned long stream);
- void LongToHex(unsigned long num,char *hexStr);
- void LongToIPAddr(unsigned long num,char *ipStr);
- void CNumToString(unsigned long num,char *str);
- short GetDriverRefNum(StringPtr dName,Boolean *isOpen);
- OSErr PostNotify(StringPtr notifStr);
-
- /*** FUNCTIONS ***/
-
- // installs our patch to _ExitToShell
- //
- void InstallZapTCP(void)
- {
- long etsPatch;
-
- etsAddr = NGetTrapAddress(_ExitToShell,ToolTrap);
- etsPatch = (long)StripAddress((Ptr)ExitToShellPatch);
- NSetTrapAddress(etsPatch,_ExitToShell,ToolTrap);
- }
-
-
- // this is our _ExitToShell patch, which will be called when the app crashes or quits.
- // it even gets called on force-quits and bus errors.
- //
- pascal void ExitToShellPatch(void)
- {
- long savedA5;
- long etsNext,etsOld,ourEtsPatch;
-
- savedA5 = SetCurrentA5();
- etsNext = etsAddr;
- etsNext++;
- etsNext--; /* generate additional references so it doesn't optimize out */
- ZapTCP();
- SetA5(savedA5);
-
- // unpatch ourselves (if nobody has patched in the meantime
-
- etsOld = NGetTrapAddress(_ExitToShell,ToolTrap);
- ourEtsPatch = (long)StripAddress((Ptr)ExitToShellPatch);
- if (etsOld==ourEtsPatch) {
- NSetTrapAddress(etsNext,_ExitToShell,ToolTrap);
- }
-
- asm {
- move.l etsNext,a0
- unlk a6
- move.l a0,-(sp)
- rts
- }
- }
-
-
- // here's the patch code. this is called on response to _ExitToShell, and searches the
- // list of open streams for streams in our heap. if it finds any, those streams are released.
- //
- OSErr ZapTCP(void)
- {
- THz theZone;
- short drvrRefNum;
- OSErr err;
- TCPiopb tcpBlock;
- StreamPtr *curStream;
- long theStream;
- unsigned long streamIndex,maxStreams;
- Boolean isOpen;
-
- theZone = ApplicZone();
-
- // get the MacTCP driver refnum, exiting if it never opened
-
- drvrRefNum = GetDriverRefNum("\p.ipp",&isOpen);
- if (!isOpen)
- return noErr;
-
- // call TCPGlobalInfo, which returns a list of the open connections and streams
-
- tcpBlock.ioCRefNum = drvrRefNum;
- tcpBlock.csCode = TCPGlobalInfo;
- err = PBControl((ParmBlkPtr)&tcpBlock,false);
- if (err!=noErr)
- return err;
-
- // check each stream to see if its buffers are in our application heap. if so,
- // release the connection via TCPAbort and TCPRelease.
-
- curStream = *tcpBlock.csParam.globalInfo.tcpCDBTable;
- maxStreams = tcpBlock.csParam.globalInfo.tcpParamPtr->tcpMaxConn;
-
- for (streamIndex=0; streamIndex<maxStreams; streamIndex++,curStream++) {
-
- theStream = *curStream;
-
- if (theStream && (theStream%2)==0 && PtrZone((Ptr)theStream)==theZone) { // only release streams in our heap
-
- tcpBlock.csCode = TCPStatus;
- tcpBlock.tcpStream = theStream;
- err = PBControl((ParmBlkPtr)&tcpBlock,false);
-
- if (err==noErr)
- AlertConnReleased(tcpBlock.csParam.status.remoteHost,(unsigned short)tcpBlock.csParam.status.remotePort);
- else
- AlertStreamReleased(theStream);
-
- // abort connection
-
- tcpBlock.csCode = TCPAbort;
- tcpBlock.tcpStream = theStream;
- err = PBControl((ParmBlkPtr)&tcpBlock,false);
-
- // release stream
-
- tcpBlock.csCode = TCPRelease;
- tcpBlock.tcpStream = theStream;
- err = PBControl((ParmBlkPtr)&tcpBlock,false);
- }
- }
-
- return err;
- }
-
-
- // notify the user that a connection was closed
- //
- void AlertConnReleased(unsigned long remoteHost,unsigned short remotePort)
- {
- char hostStr[256];
- char portStr[256];
- char *messageStr;
-
- messageStr = (char *)NewPtrSys(256);
- if (MemError()!=noErr)
- return;
-
- LongToIPAddr(remoteHost,hostStr);
- CNumToString(remotePort,portStr);
-
- strcpy(messageStr,"Warning: TCP connection released (remote addr: ");
- strcat(messageStr,hostStr);
- strcat(messageStr," remote port: ");
- strcat(messageStr,portStr);
- strcat(messageStr,")");
-
- c2pstr(messageStr);
- PostNotify((StringPtr)messageStr);
- }
-
-
- // notify the user that a stream not associated with a connection was released
- //
- void AlertStreamReleased(unsigned long stream)
- {
- char streamStr[256];
- char *messageStr;
-
- messageStr = (char *)NewPtrSys(256);
- if (MemError()!=noErr)
- return;
-
- LongToHex(stream,streamStr);
-
- strcpy(messageStr,"Warning: TCP stream released (memory location: $");
- strcat(messageStr,streamStr);
- strcat(messageStr,")");
-
- c2pstr(messageStr);
- PostNotify((StringPtr)messageStr);
- }
-
-
- // convert a long into a hex string for display
- //
- void LongToHex(unsigned long num,char *hexStr)
- {
- unsigned long nibble;
- short bitCount;
- char hexChar[2];
-
- hexChar[1] = '\0';
- hexStr[0] = '\0';
-
- for (bitCount=0; bitCount<32; bitCount+=4) {
- nibble = ((num & 0xf0000000) >> 28) & 0x0000000f;
- num = num << 4;
- if (nibble<=9 && nibble>=0)
- hexChar[0] = '0'+(char)nibble;
- else if (nibble>=10 && nibble <= 15)
- hexChar[0] = 0x37+(char)nibble;
- else
- Debugger();
- strcat(hexStr,hexChar);
- }
- }
-
-
- // convert a long into an ip address (x.x.x.x) for display
- //
- void LongToIPAddr(unsigned long num,char *ipStr)
- {
- short bitCount;
- unsigned long octet;
- char octStr[256];
-
- ipStr[0] = '\0';
- for (bitCount=0; bitCount<32; bitCount+=8) {
- octet = ((num & 0xff000000) >> 24) & 0x000000ff;
- num = num << 8;
- CNumToString(octet,octStr);
- strcat(ipStr,octStr);
- if (bitCount!=24)
- strcat(ipStr,".");
- }
- }
-
-
- // convert a number into a C string for display
- //
- void CNumToString(unsigned long num,char *str)
- {
- unsigned long place,digit;
- char addStr[2];
- Boolean firstDig;
-
- str[0] = '\0';
- addStr[1] = '\0';
- firstDig = true;
-
- for (place = 1000000000; place!=0; place = place/10) {
- digit = num/place;
- num -= (place*digit);
- if (digit)
- firstDig = false;
- if (digit>0 || !firstDig || (num==0&&place==1)) {
- addStr[0] = '0'+(char)digit;
- strcat(str,addStr);
- }
- }
- }
-
-
- // get the refnum of a driver given its name, and tell us whether it's already open
- //
- short GetDriverRefNum(StringPtr dName,Boolean *isOpen)
- {
- short negCount;
- DCtlHandle dceH;
- Ptr drivePtr;
- StringPtr s;
- short drvrRefNum;
-
- #ifdef __SYSEQU__
- negCount = -* (short *) (UnitNtryCnt);
- #else
- negCount = -UnitNtryCnt;
- #endif
-
- // check to see that driver is installed, obtain refnum
-
- drvrRefNum = -12+1;
-
- do {
- dceH = GetDCtlEntry(--drvrRefNum);
- s = (StringPtr)"";
- if ((dceH != nil) && ((**dceH).dCtlDriver!=nil)) {
- if ((**dceH).dCtlFlags & kRAMBasedMask)
- drivePtr = *((Handle)(**dceH).dCtlDriver);
- else
- drivePtr = (Ptr) (**dceH).dCtlDriver;
- if (drivePtr!=nil) {
- s = (StringPtr)(drivePtr+kDriverNameOffset);
- }
- }
- } while ((drvrRefNum!=negCount) && (EqualString(dName,s,false,true)==false));
-
- if (EqualString(dName,s,false,true)==false)
- drvrRefNum = 0;
- else
- *isOpen = ((**dceH).dCtlFlags & kDrvrOpenMask)!=0;
-
- return drvrRefNum;
- }
-
-
- // use the notification manager to post a notification alert to the user
- //
- OSErr PostNotify(StringPtr notifStr)
- {
- OSErr err;
- NMRecPtr nmPtr;
-
- nmPtr = (NMRecPtr) NewPtrSys(sizeof(NMRec));
- if (MemError()!=noErr)
- return MemError();
-
- nmPtr->qType = nmType;
- nmPtr->nmMark = 0;
- nmPtr->nmIcon = nil;
- nmPtr->nmSound = 0;
- nmPtr->nmStr = notifStr;
- nmPtr->nmResp = nil;
-
- err = NMInstall(nmPtr);
-
- return err;
- }
-
-